package GameMaze;

import java.awt.Frame;
import java.util.HashMap;
import java.util.Observable;
import java.util.Random;

import javax.swing.JOptionPane;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

import controller.Presenter;
import view.Board;
import view.View;

public class GameMazeView extends Observable implements View, Runnable {
	Display display;
	Shell shell;
	Board board;
	Label score;
	int userCommand = -1;
	Random rnd = new Random();
	String filePath = "";
	double cellNumberX = 0;
	double cellNumberY = 0;
	boolean won = false,autoSolver = false;

	//private HashMap<Integer, Image> cellsValue = new HashMap<Integer, Image>();

	Image starterCell = new Image(display, "src/GameMaze/images/free.png");
	int starterCellH = starterCell.getBounds().height;
	int starterCellW = starterCell.getBounds().width;
	

	private void initComponents() {
		display = new Display();
		shell = new Shell(display);
		shell.setLayout(new GridLayout(2, false));
		shell.setSize(starterCellW * 6, (int) (starterCellH * 5.5));
		shell.setText("Maze");
		int currentScore = 0;
		final HashMap<Integer, Image> cells = new HashMap<Integer, Image>();
		cells.put(0, new Image(display, "src/GameMaze/images/free.png"));
		cells.put(-1, new Image(display, "src/GameMaze/images/wall.png"));
		cells.put(1, new Image(display, "src/GameMaze/images/mouse.png"));
		cells.put(2, new Image(display, "src/GameMaze/images/cheese.png"));
		cells.put(3, new Image(display, "src/GameMaze/images/mouse_with_cheese.png"));

		board = new Board(5, 5, shell, SWT.BORDER,"maze",cells);
		board.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 2));
		board.setFocus();
		
		cellNumberX = board.getBoardColumns() - 1;
		cellNumberY = board.getBoardRows() - 1;

		Button btnNewGame = new Button(shell, SWT.PUSH);
		btnNewGame.setText("New Game");
		btnNewGame.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
		
		Button btnUndo = new Button(shell, SWT.PUSH);
		btnUndo.setText("Undo");
		btnUndo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));

		Button btnSave = new Button(shell, SWT.PUSH);
		btnSave.setText("Save");
		btnSave.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));

		Button btnLoad = new Button(shell, SWT.PUSH);
		btnLoad.setText("Load");
		btnLoad.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		
		Button btnHint = new Button(shell, SWT.PUSH);
		btnHint.setText("Hint");
		btnHint.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
		
		Button btnAutoSolver = new Button(shell, SWT.PUSH);
		btnAutoSolver.setText("Auto solver");
		btnAutoSolver.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));


		score = new Label(shell, SWT.NULL);
		score.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 2));
		score.setText("Score: " + currentScore);
	

		clearBoard();

		shell.open();

		board.addMouseMoveListener(new MouseMoveListener() {
			
			@Override
			public void mouseMove(MouseEvent e) {
				int boardCellSizeX = board.getSize().x / cells.size();
				int boardCellSizeY = board.getSize().y / cells.size();
				double tmpCellNumberX = (e.x / boardCellSizeX);
				double tmpCellNumberY = (e.y / boardCellSizeY);
//				}
				userCommand = 1000 * (int)tmpCellNumberX + 100 * (int)tmpCellNumberY;
				setChanged();
				notifyObservers();
											}
		});
		board.addKeyListener(new KeyListener() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.keyCode != userCommand) {
					if (e.keyCode == SWT.ARROW_UP
							|| e.keyCode == SWT.ARROW_DOWN
							|| e.keyCode == SWT.ARROW_LEFT
							|| e.keyCode == SWT.ARROW_RIGHT) {
						userCommand += e.keyCode;
					}
				}
				setChanged();
				notifyObservers();
			}

			@Override
			public void keyPressed(KeyEvent e) {
				userCommand = 0;
				if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN
						|| e.keyCode == SWT.ARROW_LEFT
						|| e.keyCode == SWT.ARROW_RIGHT) {
					autoSolver = false;
					userCommand += e.keyCode;
				}
			}
		});
		
		

		btnNewGame.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				clearBoard();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		btnUndo.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				userCommand = -4;
				setChanged();
				notifyObservers();
				board.redraw();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		btnSave.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				FileDialog dlg = new FileDialog(shell, SWT.SAVE);
				dlg.setFilterExtensions(new String[] { "*.xml" });
				String fileName = dlg.open();
				if (fileName != "") {
					filePath = fileName;
				}
				userCommand = -2;
				setChanged();
				notifyObservers();
				board.setFocus();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		btnLoad.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				FileDialog dlg = new FileDialog(shell, SWT.OPEN);
				dlg.setFilterExtensions(new String[] { "*.xml" });
				String fileName = dlg.open();
				if (fileName != "" && fileName != null) {
					filePath = fileName;
					userCommand = -3;
					setChanged();
					notifyObservers();
				}
				board.setFocus();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		btnHint.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				userCommand = -5;
				setChanged();
				notifyObservers();
				
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		
		
		
		});
		btnAutoSolver.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				if(!autoSolver){
				autoSolver = true;
				userCommand = -5;
				setChanged();
				notifyObservers();
				}
				else {
					autoSolver = false;
				}
				
			}
		
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		
		
		
		});

		
		
	}

	private void clearBoard() {
		won = false;
		userCommand = -1;
		setChanged();
		notifyObservers();
		//board.redraw();
	}

	@Override
	public void run() {
		initComponents();
		while (!shell.isDisposed()) {
				if (!display.readAndDispatch()) {
					if(won){

						Object[] options = {"Restart",
			                    "EXIT"};
						int n = JOptionPane.showOptionDialog(new Frame(),
						    "You won!!! \n what would you like to do? ",
						    "",
						    JOptionPane.YES_NO_CANCEL_OPTION,
						    JOptionPane.QUESTION_MESSAGE,
						    null,
						    options,
						    options[1]);
							if(n == -1 || n == 1){
								shell.getDisplay().dispose();
								System.exit(0);
							}
							else if (n == 0) {
								clearBoard();
								
							}
					}
				display.sleep();
				if(autoSolver){  //needs to add a sleep thred to let the player the option to abort the Auto Solver
					setChanged();
					notifyObservers();
				}
			}
		}
		//display.dispose();
	}

	@Override
	public void displayData(final int currentScore, final int[][] data) {
				for (int i = 0; i < data.length; i++) {
					for (int j = 0; j < data[i].length; j++) {
						board.newBoardData[j][i].setValue(data[i][j]);
					}
				}
				score.setText("Score:\n" + currentScore);

				board.setFocus();
				chekIsWon(data);
			}

	private void chekIsWon(int[][] data) {
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data.length; j++) {
				if (data[i][j] == 3) {
					won =  true;
					
				}
				
			}
			
		}
	}

	@Override
	public int getUserCommand() {
		return userCommand;
	}

	@Override
	public void addObserver(Presenter p) {
		super.addObserver(p);
	}

	@Override
	public void updateMe(int currentScore, int[][] data) {
		displayData(currentScore, data);
		board.setFocus();

		
	}

	@Override
	public int getCurrentCommand() {
		return userCommand;
	}

	@Override
	public String getFilePath() {
		return filePath;
	}

}
